﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Numerics
{
    public sealed class BigIntegerRandom : IBigIntegerRandom
    {
        #region Fields

        private readonly Random _random;

        #endregion

        #region Constructors

        public BigIntegerRandom()
        {
            _random = new Random();
        }

        public BigIntegerRandom(int seed)
        {
            _random = new Random();
        }

        #endregion

        #region Methods

        public BigInteger Next(int size)
        {
            BigInteger result;
            byte[] array = new byte[size];
            do
            {
                _random.NextBytes(array);
                array[array.Length - 1] &= 0x7f;
                result = new BigInteger(array);
            } while (result.ToByteArray().Length != size);
            return result;
        }

        public BigInteger Next(BigInteger maximum)
        {
            byte[] array = maximum.ToByteArray();
            // maximum available value of the first byte
            byte maximumFirstByte = array[array.Length - 1];
            _random.NextBytes(array);
            if (array[array.Length - 1] >= maximumFirstByte)
            {
                byte newFirstByte = (byte) _random.Next(0, maximumFirstByte);
                array[array.Length - 1] = newFirstByte;
            }
            return new BigInteger(array);
        }

        public BigInteger Next(BigInteger from, BigInteger to)
        {
            return Next(to - from) + from;
        }

        #endregion
    }
}
